﻿#pragma once

#include <qobject.h>
#include <qtimer.h>
#include "ScriptRunner.h"
#include "RegisterCenter_Device.h"
#include "Device.h"

template <class ConditionClass>
class StateChecker :public QObject
{
private:
  ConditionClass(Device::*stateFlagGetter)()=Q_NULLPTR;
  ConditionClass condition;
  QTimer timer_ifConditionNext;
  uint deviceId=0;
  int timeLimit = 0;
  int count_checkRunningState = 0;//状态检查计数
  int timeInterval_ifNext = 300;//检查状态时间间隔

  ScriptRunner* scriptRunner = Q_NULLPTR;
  RegisterCenter_Device* registerCenter_Device = Q_NULLPTR;

private:
  explicit StateChecker(){}
  virtual ~StateChecker(){}
public:
  static bool next_ifConditionReached(ConditionClass(Device::*stateFlagGetter)(),
                                      ConditionClass condition,
                                      uint deviceId,
                                      ScriptRunner* scriptRunner)
  {
    StateChecker<ConditionClass>* temp = new StateChecker<ConditionClass>();
    return temp->start(stateFlagGetter,
                       condition,
                       scriptRunner->getInterval_turnTableOperationTimeOut(),
                       deviceId,
                       scriptRunner,
                       scriptRunner->getRegisterCenter_Device());
  }
private:
  /*开启状态位检查，在限制的时间内，若被检查的状态位达到被期望的状态则发送信号signal_conditionReached，然后自我销毁。超过限制时间会发送信号signal_timerOut，然后自我销毁。
        返回true代表状态位检查开启成功，返回false代表状态位检查开启失败。
        类型参数ConditionClass：被检查的状态位的类型，参数stateFlag：被检查的状态位的指针，参数condition：被检查的状态位被期望达到的状态，参数timeLimit：检查时间限制，单位是毫秒。*/
  bool start(ConditionClass(Device::*stateFlagGetter)(),
             ConditionClass condition,
             int timeLimit,
             uint deviceId,
             ScriptRunner* scriptRunner,
             RegisterCenter_Device* registerCenter_Device)
  {
    if (timeLimit <= 0 ||
        stateFlagGetter == Q_NULLPTR ||
        scriptRunner == Q_NULLPTR ||
        registerCenter_Device == Q_NULLPTR)
      {
        return false;
      }
    this->stateFlagGetter = stateFlagGetter;
    this->condition = condition;
    this->timeLimit = timeLimit;
    this->deviceId=deviceId;
    this->scriptRunner = scriptRunner;
    this->registerCenter_Device=registerCenter_Device;
    connect(&timer_ifConditionNext, &QTimer::timeout, this, &StateChecker::slot_timer_ifConditionNext_timerOut);
    timer_ifConditionNext.start(timeLimit);
    return true;
  }
private:
  void slot_timer_ifConditionNext_timerOut()
  {
    if (count_checkRunningState * timeInterval_ifNext < timeLimit) {//如果计数器乘以计数间隔小于超时限制，执行状态判断等行为，否则直接超时处理
        Device* device=registerCenter_Device->getDeviceById(deviceId);
        if(Q_NULLPTR==device)//如果设备离线则执行
          {
            timer_ifConditionNext.stop();
//            scriptRunner->slot_targetDeviceMissed();
            deleteLater();
            return;
          }
        if ((device->*stateFlagGetter)() != condition) {//状态不满足条件，计数器自加一
            ++count_checkRunningState;
          }
        else
          {//状态满足条件，关闭条件判断计时器，执行下一条语句
            timer_ifConditionNext.stop();
//            scriptRunner->slot_conditionReached();
            deleteLater();
          }
      }
    else
      {//超时处理
        timer_ifConditionNext.stop();
        scriptRunner->slot_stateCheckerTimeOut(deviceId);
        deleteLater();
      }
  }
public:
  int getTimeInterval_ifNext()
  {
    return timeInterval_ifNext;
  }
  void setTimeInterval_ifNext(int timeInterval_ifNext)
  {
    this->timeInterval_ifNext = timeInterval_ifNext;
  }
};
